﻿using System;
using System.Collections;
using System.Data;
using DataAccessLayer.DataSets;
using DTO.Clases;
using Npgsql;

namespace DataAccessLayer.Clases
{
    /// <summary>
    /// Representa una clase de tranzacion de Base de Datos de Inventario.
    /// </summary>
    public class DaoInventario
    {
        #region Atributos

        /// <summary>
        /// Objeto de conexion a base de datos PostgreSQL.
        /// </summary>
        private Conexion miConexion;

        /// <summary>
        /// Representa un objeto de sentencias SQL a PostgreSQL.
        /// </summary>
        private NpgsqlCommand miComando;

        /// <summary>
        /// Objeto adaptador de consultas a base de datos.
        /// </summary>
        private NpgsqlDataAdapter miAdapter;

        /// <summary>
        /// Representa la funcion comprobar_inventario.
        /// </summary>
        private const string sqlComprobar = "comprobar_inventario";

        /// <summary>
        /// Representa la funcion comprobar_cantidad_inventario.
        /// </summary>
        private const string sqlComprobarCant = "comprobar_cantidad_inventario";

        /// <summary>
        /// Representa la funcion insertar_inventario_fisico.
        /// </summary>
        private const string sqlInsertarFisico = "insertar_inventario_fisico";

        /// <summary>
        /// Representa la funcion insertar_inventario.
        /// </summary>
        private const string sqlInsertar = "insertar_inventario";

        /// <summary>
        /// Representa la funcion producto_marca.
        /// </summary>
        private const string sqlProductoMarca = "producto_marca";

        /// <summary>
        /// Representa la funcion productos_corte.
        /// </summary>
        private const string sqlProductoCorte = "productos_corte";

        /// <summary>
        /// Representa la funcion productoen_resumen_inventario.
        /// </summary>
        private const string sqlProductoHistorial = "productoen_resumen_inventario";

        /// <summary>
        /// Representa la funcion count_productoen_resumen_inventario.
        /// </summary>
        private const string sqlTotalProductoHistorial = "count_productoen_resumen_inventario";

        /// <summary>
        /// Representa la funcion count_producto_corte.
        /// </summary>
        private const string sqlTotalProductoCorte = "count_producto_corte";

        /// <summary>
        /// Representa la funcino count_lista_producto_corte_pendiente.
        /// </summary>
        private const string sqlCountConsultaCorteGeneral = "count_lista_producto_corte_pendiente";

        /// <summary>
        /// Representa la funcion corte_inventario_fisico.
        /// </summary>
        private const string sqlCorteInventarioFisico = "corte_inventario_fisico";

        /// <summary>
        /// Representa la funcion consulta_inventario.
        /// </summary>
        private const string sqlConsultaInventario = "consulta_inventario";

        /// <summary>
        /// Representa la funcion insertar_resumen_inventario.
        /// </summary>
        private const string sqlInsertarResumenInventario = "insertar_resumen_inventario";

        /// <summary>
        /// Representa la funcion get_cantidad_inventario.
        /// </summary>
        private const string sqlCantidadInventario = "get_cantidad_inventario";

        /// <summary>
        /// Representa la funcion editar_inventario.
        /// </summary>
        private const string sqlEditarInventario = "editar_inventario";

        /// <summary>
        /// Representa la funcion editar_inventario_fisico.
        /// </summary>
        private const string sqlEditarInventarioFisico = "editar_inventario_fisico";

        /// <summary>
        /// Representa la funcion : producto_basico_categoria.
        /// </summary>
        private const string sqlProductoCategoria = "producto_basico_categoria";

        /// <summary>
        /// Representa la funcion count_producto_categoria.
        /// </summary>
        private const string sqlTotalRegistrosProducto = "count_producto_categoria";

        /// <summary>
        /// Representa la funcion consulta_inventario_fisico.
        /// </summary>
        private const string sqlConsultaFisico = "consulta_inventario_fisico";

        /// <summary>
        /// Representa la funcion count_corte_inventario.
        /// </summary>
        private const string sqlTotalCorteInventario = "count_corte_inventario";

        /// <summary>
        /// Representa la funcion consulta_inventario_fisico_nocolor.
        /// </summary>
        private const string sqlConsultaInventarioFisicoNoColor = "consulta_inventario_fisico_nocolor";

        /// <summary>
        /// Representa la funcion count_corte_inventario_nocolor.
        /// </summary>
        private const string sqlTotalInventarioFisicoNoColor = "count_corte_inventario_nocolor";

        /// <summary>
        /// Representa la funcion lista_resumen_inventario.
        /// </summary>
        private const string sqlResumenInventario = "lista_resumen_inventario";

        /// <summary>
        /// Representa la funcion : count_resumen_inventario.
        /// </summary>
        private const string sqlTotalResumenInventario = "count_resumen_inventario";

        /// <summary>
        /// Representa la funcion : resumen_inventario_nocolor.
        /// </summary>
        private const string sqlResumenInventarioNoColor = "resumen_inventario_nocolor";

        /// <summary>
        /// Representa la funcion : count_resumen_inventario_nocolor.
        /// </summary>
        private const string sqlTotalResumenInventarioNoColor = "count_resumen_inventario_nocolor";

        /// <summary>
        /// Representa la funcion ultimo_registro_resumen_inventario.
        /// </summary>
        private const string sqlUltimoRegistroInventario = "ultimo_registro_resumen_inventario";

        /// <summary>
        /// Representa la funcion count_ultimo_registro_resumen_inventario.
        /// </summary>
        private const string sqlTotalUltimoRegistroInventario = "count_ultimo_registro_resumen_inventario";

        /// <summary>
        /// Representa la funcion ultimo_registro_resumen_inventario_nocolor.
        /// </summary>
        private const string sqlUltimoRegistroInventarioNoColor = "ultimo_registro_resumen_inventario_nocolor";

        /// <summary>
        /// Representa la funcion resumen_inventario_fecha.
        /// </summary>
        private const string sqlResumenInventarioFecha = "resumen_inventario_fecha";

        /// <summary>
        /// Representa la funcion resumen_inventario_fecha_nocolor.
        /// </summary>
        private const string sqlResumenInventarioFechaNoColor = "resumen_inventario_fecha_nocolor";

        /// <summary>
        /// Representa la funcion count_resumen_inventario_fecha.
        /// </summary>
        private const string sqlTotalResumenInventarioFecha = "count_resumen_inventario_fecha";

        /// <summary>
        /// Representa la funcion resumen_inventario_periodo.
        /// </summary>
        private const string sqlResumenInventarioPeriodo = "resumen_inventario_periodo";

        /// <summary>
        /// Representa la funcion count_resumen_inventario_periodo.
        /// </summary>
        private const string sqlTotalInventarioPeriodo = "count_resumen_inventario_periodo";

        /// <summary>
        /// Representa la funcion resumen_inventario_periodo_nocolor.
        /// </summary>
        private const string sqlInventarioPeriodoNoColor = "resumen_inventario_periodo_nocolor";

        /// <summary>
        /// Representa la funcion count_resumen_inventario_periodo_nocolor.
        /// </summary>
        private const string sqlTotalInventarioPeriodoNoColor = "count_resumen_inventario_periodo_nocolor";

        /// <summary>
        /// Representa la funcion eliminar_inventario.
        /// </summary>
        private const string sqlEliminar = "eliminar_inventario";

        /// <summary>
        /// Representa el texto : Ocurrio un error al comprobar el inventario.
        /// </summary>
        private const string ErrorComprobar = "Ocurrio un error al comprobar el inventario.\n";

        /// <summary>
        /// Representa el texto : Ocurrio un error al ingresar el registro de inventario.
        /// </summary>
        private const string ErrorInsertar = "Ocurrio un error al ingresar el registro de inventario.\n";

        /// <summary>
        /// Represetna la funcion Ocurrio un error al actualizar los datos en inventario.
        /// </summary>
        private const string ErrorActualizar = "Ocurrio un error al actualizar los datos en inventario.\n";

        /// <summary>
        /// Representa el texto : Ocurrio un problema al cargar el registro del producto.
        /// </summary>
        private const string ErrorProducto = "Ocurrio un problema al cargar el registro del producto.\n";

        #endregion

        /// <summary>
        /// Inicializa una nueva instancia de la clase Inventario.
        /// </summary>
        public DaoInventario()
        {
            this.miConexion = new Conexion();
        }

        /// <summary>
        /// Ingresa un registro del inventario a la base de datos.
        /// </summary>
        /// <param name="inventario"></param>
        public void InsertarInventario(Inventario inventario)
        {
            try
            {
                CargarComandoStoredProcedure(sqlInsertar);
                miComando.Parameters.AddWithValue("producto", inventario.CodigoProducto);
                miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                miComando.Parameters.AddWithValue("color", inventario.IdColor);
                miComando.Parameters.AddWithValue("cantidad", inventario.Cantidad);
                miConexion.MiConexion.Open();
                miComando.ExecuteNonQuery();
                miConexion.MiConexion.Close();
                miComando.Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorInsertar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Ingresa un regsitro del inventario fisico a la base de datos.
        /// </summary>
        /// <param name="inventario">Inventario a ingresar.</param>
        public void InsertarInventarioFisico(InventarioFisico inventario)
        {
            var daoValorMedida = new DaoValorUnidadMedida();
            try
            {
                CargarComandoStoredProcedure(sqlInsertarFisico);
                miComando.Parameters.AddWithValue("fecha", inventario.Fecha.ToShortDateString());
                miComando.Parameters.AddWithValue("producto", inventario.CodigoProducto);
                miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                miComando.Parameters.AddWithValue("color", inventario.IdColor);
                miComando.Parameters.AddWithValue("cantidad", inventario.Cantidad);
                miComando.Parameters.AddWithValue("corte", inventario.Corte);
                miConexion.MiConexion.Open();
                miComando.ExecuteNonQuery();
                miConexion.MiConexion.Close();
                miComando.Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorInsertar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
            Inventario miInventario = new Inventario();
            miInventario.CodigoProducto = inventario.CodigoProducto;
            miInventario.IdMedida = inventario.IdMedida;
            miInventario.IdColor = inventario.IdColor;
            if (!ComprobarInventario(miInventario, true))
            {
                InsertarInventario(miInventario);
            }
            var valorMedida = new ValorUnidadMedida();
            valorMedida.IdValorUnidadMedida = inventario.IdMedida;
            valorMedida.CodigoInternoProducto = inventario.CodigoProducto;
            if (!daoValorMedida.ComprobarMedidaProducto(valorMedida))
            {
                daoValorMedida.InsertarMedidaProducto(valorMedida);
            }
        }

        /// <summary>
        /// Comprueba la existencia de una relacion establecida de un Producto en el inventario.
        /// </summary>
        /// <param name="inventario">Inventario a comprobar.</param>
        /// <returns></returns>
        public bool ComprobarInventario(Inventario inventario, bool color)
        {
            try
            {
                CargarComandoStoredProcedure(sqlComprobar);
                miComando.Parameters.AddWithValue("producto", inventario.CodigoProducto);
                miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                if (color)
                {
                    miComando.Parameters.AddWithValue("color", inventario.IdColor);
                }
                miConexion.MiConexion.Open();
                var resultado = Convert.ToBoolean(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return resultado;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorComprobar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Comprueba si la relacion de inventario tiene cantidad superior a cero.
        /// </summary>
        /// <param name="inventario">Inventario a consultar.</param>
        /// <returns></returns>
        private bool ComprobarCantidadInventario(Inventario inventario)
        {
            try
            {
                CargarComandoStoredProcedure(sqlComprobarCant);
                miComando.Parameters.AddWithValue("codigo", inventario.CodigoProducto);
                miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                miComando.Parameters.AddWithValue("color", inventario.IdColor);
                miConexion.MiConexion.Open();
                var resultado = Convert.ToInt32(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                if (resultado == 0)
                    return true;
                else
                    return false;
            }
            catch (InvalidCastException ex)
            {
                throw new InvalidCastException(ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene el listado de los registros de los productos a cruzar en inventario.
        /// </summary>
        /// <param name="registroBase">Registro base para la consulta.</param>
        /// <param name="registrosMaximos">Registros maximos a recuperar.</param>
        /// <returns></returns>
        public DataTable ProductoConCorte(int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlProductoCorte);
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "producto_corte");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registros de los productos a cruzar en inventario.
        /// </summary>
        /// <returns></returns>
        public long GetTotalRowProductoConCorte()
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalProductoCorte);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        ///  Obtiene el listado de los registros de los productos en inventario.
        /// </summary>
        /// <param name="registroBase">Registro base para la consulta.</param>
        /// <param name="registrosMaximos">Registros maximos a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultaProductoResumenInventario(int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlProductoHistorial);
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "producto_historial");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registros de los productos en inventario.
        /// </summary>
        /// <returns></returns>
        public long GetRowsConsultaProductoResumenInventario()
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalProductoHistorial);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene el listado de los registros de los productos a cruzar en inventario con sus cifras.
        /// </summary>
        /// <param name="orden">Establece el valor que indica el numero de orden de los registros.</param>
        /// <param name="registroBase">Registro base para la consulta.</param>
        /// <param name="registrosMaximos">Registro base para la consulta.</param>
        /// <returns></returns>
        public DataTable ConsultaCorteGeneral(int orden, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            var miTabla = TablaInventario();
            try
            {
                if (orden == 1)
                {
                    CargarAdapterStoredProcedure("lista_producto_corte_pendiente");
                }
                else
                {
                    if (orden == 2)
                    {
                        CargarAdapterStoredProcedure("lista_producto_corte_pendiente_nombre");
                    }
                    else
                    {
                        CargarAdapterStoredProcedure("lista_producto_corte_pendiente_nombre_desc");
                    }
                }
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "inventario");
                var tabla = dataSet.Tables[0];
                foreach (DataRow row in tabla.Rows)
                {
                    var row_ = miTabla.NewRow();
                    var codigo = Convert.ToString(row["codigointernoproducto"]);
                    var idMedida = Convert.ToInt32(row["idvalor_unidad_medida"]);
                    var idColor = Convert.ToInt32(row["idcolor"]);
                    var color = new ElColor();
                    color.MapaBits = (string)row["stringcolor"];
                    if (ComprobarRegistroInventarioFisico(codigo, idMedida, idColor))
                    {
                        var inventario = RegistroInventarioFisico(codigo, idMedida, idColor);
                        row_["Fecha"] = inventario.Fecha;
                        row_["Fisico"] = inventario.Cantidad.ToString();
                        row_["Estado"] = true;
                    }
                    else
                    {
                        row_["Fisico"] = "---";
                        row_["Estado"] = false;
                    }
                    row_["Codigo"] = row["codigointernoproducto"];
                    row_["Nombre"] = row["nombreproducto"];
                    row_["Marca"] = row["nombremarca"];
                    row_["Unidad"] = row["descripcionunidad_medida"];
                    row_["Medida"] = row["descripcionvalor_unidad_medida"];
                    row_["Color"] = color.ImagenBit;
                    row_["Inventario"] = "---";
                    row_["Diferencia"] = "---";
                    miTabla.Rows.Add(row_);
                }
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Comprueba la la existencia del registro en Inventario Fisico.
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar</param>
        /// <param name="idMedida">Id de la Medida a consultar.</param>
        /// <param name="idColor">Id del color a consultar.</param>
        /// <returns></returns>
        private bool ComprobarRegistroInventarioFisico
            (string codigo, int idMedida, int idColor)
        {
            try
            {
                CargarComandoStoredProcedure("comprobar_registro_inventario_fisico");
                miComando.Parameters.AddWithValue("codigo", codigo);
                miComando.Parameters.AddWithValue("medida", idMedida);
                miComando.Parameters.AddWithValue("color", idColor);
                miConexion.MiConexion.Open();
                var resultado = Convert.ToBoolean(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return resultado;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene un registro de Inventario Fisico.
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <param name="idMedida">Id de la Medida a consultar.</param>
        /// <param name="idColor">Id del Color a Consultar.</param>
        /// <returns></returns>
        private InventarioFisico RegistroInventarioFisico
            (string codigo, int idMedida, int idColor)
        {
            try
            {
                CargarComandoStoredProcedure("registro_producto_inventario_fisico");
                miComando.Parameters.AddWithValue("codigo", codigo);
                miComando.Parameters.AddWithValue("medida", idMedida);
                miComando.Parameters.AddWithValue("color", idColor);
                miConexion.MiConexion.Open();
                NpgsqlDataReader miReader = miComando.ExecuteReader();
                var inventario = new InventarioFisico();
                while (miReader.Read())
                {
                    inventario.Fecha = miReader.GetDateTime(1);
                    inventario.Cantidad = miReader.GetDouble(5);
                }
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return inventario;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        ///  Obtiene el total de registros de los productos a cruzar en inventario.
        /// </summary>
        /// <returns></returns>
        public long GetRowsConsultaCorteGeneral()
        {
            try
            {
                CargarComandoStoredProcedure(sqlCountConsultaCorteGeneral);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Realiza el cruce entre el inventario ingresado y el inventario de sistema.
        /// </summary>
        /// <param name="inventarioSistema">Indica si continua con las cifras de cantidad del sistema.</param>
        /// <param name="fecha">Fecha en que se realiza el cruce</param>
        public void CruzarInventario(bool inventarioSistema, bool firstCorte, DateTime fecha)
        {
            try
            {
                var tablaCorteInventario = CorteInventario();
                foreach (DsInventarios.view_corte_inventario_fisicoRow rowFisico
                                                    in tablaCorteInventario.Rows)
                {
                    var inventario = new Inventario();
                    inventario.CodigoProducto = rowFisico.codigointernoproducto;
                    inventario.IdMedida = rowFisico.idvalor_unidad_medida;
                    inventario.IdColor = rowFisico.idcolor;
                    var tablaInventario = ConsultaInventario(inventario);
                    foreach (DsInventarios.view_inventarioRow rowInventario
                                                    in tablaInventario.Rows)
                    {
                        var resultado = rowFisico.cantidad_inventario_fisico - rowInventario.cantidad_inventario;
                        var resumen = new ResumenInventario();
                        resumen.Fecha = fecha;
                        resumen.CodigoProducto = rowFisico.codigointernoproducto;
                        resumen.IdMedida = rowFisico.idvalor_unidad_medida;
                        resumen.IdColor = rowFisico.idcolor;
                        resumen.Cantidad = rowInventario.cantidad_inventario;
                        resumen.CantidadFisico = rowFisico.cantidad_inventario_fisico;
                        resumen.CantidadResumen = resultado;
                        resumen.ValorProducto = rowFisico.valorventaproducto;
                        IngresarResumenInventario(resumen);
                        if (!inventarioSistema || firstCorte)
                        {
                            ActualizarInventario
                                (rowInventario.id_inventario, rowFisico.cantidad_inventario_fisico);
                        }
                        ActualizarInventarioFisico(rowFisico.id_inventario_fisico);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el listado de los registros de producto por cruzar en inventario.
        /// </summary>
        /// <returns></returns>
        private DataTable CorteInventario()
        {
            var tabla = new DataSets.DsInventarios.view_corte_inventario_fisicoDataTable();
            try
            {
                CargarAdapterStoredProcedure(sqlCorteInventarioFisico);
                miAdapter.Fill(tabla);
                return tabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el listado de los registros de producto en inventario.
        /// </summary>
        /// <param name="inventario">Inventario a consultar.</param>
        /// <returns></returns>
        private DataTable ConsultaInventario(Inventario inventario)
        {
            var tabla = new DataSets.DsInventarios.view_inventarioDataTable();
            try
            {
                CargarAdapterStoredProcedure(sqlConsultaInventario);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", inventario.CodigoProducto);
                miAdapter.SelectCommand.Parameters.AddWithValue("medida", inventario.IdMedida);
                miAdapter.SelectCommand.Parameters.AddWithValue("color", inventario.IdColor);
                miAdapter.Fill(tabla);
                return tabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }
        
        /// <summary>
        /// Ingresa un registro del resumen de inventario en la base de datos.
        /// </summary>
        /// <param name="inventario">Registro de inventario a ingresar.</param>
        private void IngresarResumenInventario(ResumenInventario inventario)
        {
            try
            {
                CargarComandoStoredProcedure(sqlInsertarResumenInventario);
                miComando.Parameters.AddWithValue("fecha", inventario.Fecha);
                miComando.Parameters.AddWithValue("producto", inventario.CodigoProducto);
                miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                miComando.Parameters.AddWithValue("color", inventario.IdColor);
                miComando.Parameters.AddWithValue("cantidad", inventario.Cantidad);
                miComando.Parameters.AddWithValue("fisico", inventario.CantidadFisico);
                miComando.Parameters.AddWithValue("resumen", inventario.CantidadResumen);
                miComando.Parameters.AddWithValue("valor", inventario.ValorProducto);
                miConexion.MiConexion.Open();
                miComando.ExecuteNonQuery();
                miConexion.MiConexion.Close();
                miComando.Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorInsertar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Actualiza la cantidad del inventario en la base de datos.
        /// </summary>
        /// <param name="id">Id del registro de inventario a actualziar.</param>
        /// <param name="cantidad">Cantidad a actualizar en inventario.</param>
        private void ActualizarInventario(int id, double cantidad)
        {
            try
            {
                CargarComandoStoredProcedure(sqlEditarInventario);
                miComando.Parameters.AddWithValue("id", id);
                miComando.Parameters.AddWithValue("cantidad", cantidad);
                miConexion.MiConexion.Open();
                miComando.ExecuteNonQuery();
                miConexion.MiConexion.Close();
                miComando.Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorActualizar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Actualzia el registro de corte de inventario en true.
        /// </summary>
        /// <param name="id">Id del registro a actualizar.</param>
        private void ActualizarInventarioFisico(int id)
        {
            try
            {
                CargarComandoStoredProcedure(sqlEditarInventarioFisico);
                miComando.Parameters.AddWithValue("id", id);
                miConexion.MiConexion.Open();
                miComando.ExecuteNonQuery();
                miConexion.MiConexion.Close();
                miComando.Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorActualizar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene el registro de producto en cuestion
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <returns></returns>
        public DataTable ConsultarProducto(string codigo)
        {
            var tabla = new DataTable();
            try
            {
                CargarAdapterStoredProcedure(sqlProductoMarca);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill(tabla);
                return tabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene los registro de los productos en una Categoria.
        /// </summary>
        /// <param name="codigo">Codigo de la Categoria.</param>
        /// <param name="registroBase">Registro base para la consulta.</param>
        /// <param name="registrosMaximos">Numero de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultaProductoPorCategoria
            (string codigo, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlProductoCategoria);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill
                    (dataSet, registroBase, registrosMaximos, "producto_basico");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registros de producto en una consulta.
        /// </summary>
        /// <returns></returns>
        public long GetTotalRowProducto(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalRegistrosProducto);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally
            { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene los registros de producto en inventario fisico.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultarInventarioFisico
            (string codigo, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlConsultaFisico);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill
                    (dataSet, registroBase, registrosMaximos, "inventario_fisico");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta de producto en inventario fisico.
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <returns></returns>
        public long GetTotalRowCorteInventario(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalCorteInventario);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally
            { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene los registros de producto en inventario fisico.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultarInventarioFisicoNoColor
            (string codigo, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlConsultaInventarioFisicoNoColor);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill
                    (dataSet, registroBase, registrosMaximos, "inventario_fisico");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta de producto en inventario fisico.
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <returns></returns>
        public long GetRowsInventarioFisicoNoColor(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalInventarioFisicoNoColor);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene el listado de los registros de los productos cruzados en inventario con sus cifras.
        /// </summary>
        /// <param name="orden">Establece el valor que indica el numero de orden de los registros.</param>
        /// <param name="registroBase">Registro base para la consulta.</param>
        /// <param name="registrosMaximos">Registro base para la consulta.</param>
        /// <returns></returns>
        public DataTable ConsultaResumenInventario(int orden, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            var miTabla = TablaInventario();
            try
            {
                if (orden == 1)
                {
                    CargarAdapterStoredProcedure("lista_producto_resumen_inventario");
                }
                else
                {
                    if (orden == 2)
                    {
                        CargarAdapterStoredProcedure("lista_producto_resumen_inventario_nombre");
                    }
                    else
                    {
                        CargarAdapterStoredProcedure("lista_producto_resumen_inventario_nombre_desc");
                    }
                }
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "inventario");
                foreach (DataRow row in dataSet.Tables[0].Rows)
                {
                    var row_ = miTabla.NewRow();
                    var color = new ElColor();
                    color.MapaBits = (string)row["stringcolor"];
                    row_["Codigo"] = row["codigointernoproducto"];
                    row_["Nombre"] = row["nombreproducto"];
                    row_["Marca"] = row["nombremarca"];
                    row_["Fecha"] = row["fecha_resumen"];
                    row_["Unidad"] = row["descripcionunidad_medida"];
                    row_["Medida"] = row["descripcionvalor_unidad_medida"];
                    row_["Color"] = color.ImagenBit;
                    row_["Inventario"] = row["cantidad_inventario"];
                    row_["Fisico"] = row["cantidad_inventario_fisico"];
                    row_["Diferencia"] = row["cantidad_resumen"];
                    miTabla.Rows.Add(row_);
                }
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registros de Resumen de Inventario.
        /// </summary>
        /// <returns></returns>
        public long GetRowsConsultaResumenInventario()
        {
            try
            {
                CargarComandoStoredProcedure("count_lista_producto_resumen_inventario");
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene los registros de una consulta de Resumen de inventario.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ResumenInventarioColor
            (string codigo, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlResumenInventario);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill
                    (dataSet, registroBase, registrosMaximos, "resumen_inventario");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta de producto en Resumen de Inventario
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <returns></returns>
        public long GetRowsResumenInventarioColor(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalResumenInventario);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene los registros de una consulta de Resumen de inventario.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ResumenInventarioNoColor
            (string codigo, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlResumenInventarioNoColor);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill
                    (dataSet, registroBase, registrosMaximos, "resumen_inventario");
                return dataSet.Tables[0];
            }
            catch(Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta de producto en Resumen de Inventario
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <returns></returns>
        public long GetRowsResumenInventarioNoColor(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalResumenInventarioNoColor);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene el ultimo registro del producto en el Resumen de Inventario
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="color">Indica si la consulta incluye color en el producto.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable UltimoRegistroInventario
            (string codigo, bool color, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                if (color)
                    CargarAdapterStoredProcedure(sqlUltimoRegistroInventario);
                else
                    CargarAdapterStoredProcedure(sqlUltimoRegistroInventarioNoColor);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "resumen_inventario");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta de producto en Resumen de Inventario
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <returns></returns>
        public long GetRowsUltimoRegistroInventario(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalUltimoRegistroInventario);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene los registros de una consulta por fecha de Resumen de inventario.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="fecha">Fecha a la cual se hace referencia.</param>
        /// <param name="color">Indica si la consulta incluye color en el producto.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultaInventarioFecha
          (string codigo, DateTime fecha, bool color, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                if (color)
                    CargarAdapterStoredProcedure(sqlResumenInventarioFecha);
                else
                    CargarAdapterStoredProcedure(sqlResumenInventarioFechaNoColor);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.SelectCommand.Parameters.AddWithValue("fecha", fecha);
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "resumen_inventario");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta por fecha de producto en Resumen de Inventario.
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <param name="fecha">Fecha a la cual se hace referencia.</param>
        /// <returns></returns>
        public long GetRowsConsultaInventarioFecha(string codigo, DateTime fecha)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalResumenInventarioFecha);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miComando.Parameters.AddWithValue("fecha", fecha);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene los registros de una consulta por periodo de fecha de Resumen de inventario.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="fecha1">Fecha inicial a la cual se hace referencia.</param>
        /// <param name="fecha2">Fecha final a la cual se hace referencia.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultaInventarioPeriodo
            (string codigo, DateTime fecha1, DateTime fecha2, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlResumenInventarioPeriodo);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.SelectCommand.Parameters.AddWithValue("fecha1", fecha1);
                miAdapter.SelectCommand.Parameters.AddWithValue("fecha2", fecha2);
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "resumen_inventario");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta por periodo de fecha de Resumen de Inventario.
        /// </summary>
        /// <param name="codigo">Codigo del Producto a consultar.</param>
        /// <param name="fecha1">Fecha inicial a la cual se hace referencia.</param>
        /// <param name="fecha2">Fecha final a la cual se hace referencia.</param>
        /// <returns></returns>
        public long GetRowsConsultaInventarioPeriodo(string codigo, DateTime fecha1, DateTime fecha2)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalInventarioPeriodo);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miComando.Parameters.AddWithValue("fecha1", fecha1);
                miComando.Parameters.AddWithValue("fecha2", fecha2);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene los registros de una consulta por periodo de fecha de Resumen de inventario sin incluir color.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="fecha1">Fecha inicial a la cual se hace referencia.</param>
        /// <param name="fecha2">Fecha final a la cual se hace referencia.</param>
        /// <param name="registroBase">Registros base para la consulta.</param>
        /// <param name="registrosMaximos">Número de registros a recuperar.</param>
        /// <returns></returns>
        public DataTable ConsultaInventarioPeriodoNoColor
            (string codigo, DateTime fecha1, DateTime fecha2, int registroBase, int registrosMaximos)
        {
            var dataSet = new DataSet();
            try
            {
                CargarAdapterStoredProcedure(sqlInventarioPeriodoNoColor);
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.SelectCommand.Parameters.AddWithValue("fecha1", fecha1);
                miAdapter.SelectCommand.Parameters.AddWithValue("fecha2", fecha2);
                miAdapter.Fill(dataSet, registroBase, registrosMaximos, "resumen_inventario");
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el total de registro de una consulta por periodo de fecha de Resumen de Inventario sin incluir color.
        /// </summary>
        /// <param name="codigo">Codigo del producto a consultar.</param>
        /// <param name="fecha1">Fecha inicial a la cual se hace referencia.</param>
        /// <param name="fecha2">Fecha final a la cual se hace referencia.</param>
        /// <returns></returns>
        public long GetRowsConsultaInventarioPeriodoNoColor(string codigo, DateTime fecha1, DateTime fecha2)
        {
            try
            {
                CargarComandoStoredProcedure(sqlTotalInventarioPeriodoNoColor);
                miComando.Parameters.AddWithValue("codigo", codigo);
                miComando.Parameters.AddWithValue("fecha1", fecha1);
                miComando.Parameters.AddWithValue("fecha2", fecha2);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        /// <summary>
        /// Actualiza la cantidad de un registro en especifico del inventario.
        /// </summary>
        /// <param name="inventario">Inventario a actualizar.</param>
        /// <param name="venta">Indica si es una actualización por venta o no.</param>
        public void ActualizarInventario(Inventario inventario, bool venta)
        {
            try
            {
                if (!ComprobarInventario(inventario, true) && !venta)
                {
                    InsertarInventario(inventario);
                }
                else
                {
                    var cantidad = CantidadInventario(inventario);
                    CargarComandoStoredProcedure(sqlEditarInventario);
                    miComando.Parameters.AddWithValue("producto", inventario.CodigoProducto);
                    miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                    miComando.Parameters.AddWithValue("color", inventario.IdColor);
                    if (venta)
                    {
                        cantidad = cantidad - inventario.Cantidad;
                    }
                    else
                    {
                        cantidad = cantidad + inventario.Cantidad;
                    }
                    miComando.Parameters.AddWithValue("cantidad", cantidad);
                    miConexion.MiConexion.Open();
                    miComando.ExecuteNonQuery();
                    miConexion.MiConexion.Close();
                    miComando.Dispose();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorActualizar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene la cantidad de un registro de Inventario.
        /// </summary>
        /// <param name="inventario">Inventario a consultar.</param>
        /// <returns></returns>
        public double CantidadInventario(Inventario inventario)
        {
            try
            {
                CargarComandoStoredProcedure(sqlCantidadInventario);
                miComando.Parameters.AddWithValue("producto", inventario.CodigoProducto);
                miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                miComando.Parameters.AddWithValue("color", inventario.IdColor);
                miConexion.MiConexion.Open();
                var rows = Convert.ToDouble(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorComprobar + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Elimina un registro del Inventario.
        /// </summary>
        /// <param name="inventario">Inventario a eliminar.</param>
        public bool EliminarInventario(Inventario inventario)
        {
            if (ComprobarCantidadInventario(inventario))
            {
                try
                {
                    CargarComandoStoredProcedure(sqlEliminar);
                    miComando.Parameters.AddWithValue("codigo", inventario.CodigoProducto);
                    miComando.Parameters.AddWithValue("medida", inventario.IdMedida);
                    miComando.Parameters.AddWithValue("color", inventario.IdColor);
                    miConexion.MiConexion.Open();
                    miComando.ExecuteNonQuery();
                    miConexion.MiConexion.Close();
                    miComando.Dispose();
                }
                catch (Exception ex)
                {
                    throw new Exception(ErrorActualizar + ex.Message);
                }
                finally { miConexion.MiConexion.Close(); }
                return true;
            }
            else
            {
                return false;
            }
            
        }

        public DataTable ListarProductoInventario(string codigo)
        {
            var miTabla = TablaInventario();
            try
            {
                var tabla = new DataTable();
                miTabla.Columns.Add(new DataColumn("IdColor", typeof(int)));
                miTabla.Columns.Add(new DataColumn("IdValorMedida", typeof(int)));

                CargarAdapterStoredProcedure("listar_inventario_producto");
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill(tabla);

                foreach (DataRow row in tabla.Rows)
                {
                    var row_ = miTabla.NewRow();
                    var color = new ElColor();
                    color.MapaBits = (string)row["color"];
                    row_["Codigo"] = row["codigo"];
                    row_["Nombre"] = row["codigobarras"];
                    row_["Marca"] = row["nombre"];
                    row_["IdColor"] = row["idcolor"];
                    row_["Color"] = color.ImagenBit;
                    row_["Unidad"] = row["unidadmedida"];
                    row_["IdValorMedida"] = row["idvalormedida"];
                    row_["Medida"] = row["valorunidadmedida"];
                    row_["Inventario"] = row["cantidad"];
                    miTabla.Rows.Add(row_);
                }
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception("Ocurrio un problema al cargar el registro del producto.\n" + ex.Message);
            }
        }


        public DataTable ConsultaInventario(int rowBase, int rowMax)
        {
            var dataTable = new DataTable();
            var miTabla = TablaInventario();
            try
            {
                CargarAdapterStoredProcedure("listar_inventario_producto");
                miAdapter.Fill(rowBase, rowMax, dataTable);
                foreach (DataRow row in dataTable.Rows)
                {
                    var row_ = miTabla.NewRow();
                    var color = new ElColor();
                    color.MapaBits = (string)row["color"];
                    row_["Marca"] = row["categoria"];
                    row_["Codigo"] = row["codigo"];
                    row_["Nombre"] = row["nombre"];
                    row_["Unidad"] = row["unidadmedida"];
                    row_["Medida"] = row["valorunidadmedida"];
                    row_["Color"] = color.ImagenBit;
                    row_["Inventario"] = row["cantidad"];
                    miTabla.Rows.Add(row_);
                }
                dataTable.Clear();
                dataTable.Dispose();
                dataTable = null;
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        public long GetRowsConsultaInventario()
        {
            try
            {
                CargarComandoStoredProcedure("count_listar_inventario_producto");
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception("" + ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        public DataTable ConsultaInventario(string codigo, int rowBase, int rowMax)
        {
            var dataTable = new DataTable();
            var miTabla = TablaInventario();
            try
            {
                CargarAdapterStoredProcedure("listar_inventario_producto");
                miAdapter.SelectCommand.Parameters.AddWithValue("codigo", codigo);
                miAdapter.Fill(rowBase, rowMax, dataTable);
                foreach (DataRow row in dataTable.Rows)
                {
                    var row_ = miTabla.NewRow();
                    var color = new ElColor();
                    color.MapaBits = (string)row["color"];
                    row_["Marca"] = row["categoria"];
                    row_["Codigo"] = row["codigo"];
                    row_["Nombre"] = row["nombre"];
                    row_["Unidad"] = row["unidadmedida"];
                    row_["Medida"] = row["valorunidadmedida"];
                    row_["Color"] = color.ImagenBit;
                    row_["Inventario"] = row["cantidad"];
                    miTabla.Rows.Add(row_);
                }
                dataTable.Clear();
                dataTable.Dispose();
                dataTable = null;
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        public long GetRowsConsultaInventario(string codigo)
        {
            try
            {
                CargarComandoStoredProcedure("count_listar_inventario_producto");
                miComando.Parameters.AddWithValue("codigo", codigo);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        public DataTable ConsultaInventarioNombre(string nombre, int rowBase, int rowMax)
        {
            var dataTable = new DataTable();
            var miTabla = TablaInventario();
            try
            {
                CargarAdapterStoredProcedure("listar_inventario_producto_nombre");
                miAdapter.SelectCommand.Parameters.AddWithValue("nombre", nombre);
                miAdapter.Fill(rowBase, rowMax, dataTable);
                foreach (DataRow row in dataTable.Rows)
                {
                    var row_ = miTabla.NewRow();
                    var color = new ElColor();
                    color.MapaBits = (string)row["color"];
                    row_["Marca"] = row["categoria"];
                    row_["Codigo"] = row["codigo"];
                    row_["Nombre"] = row["nombre"];
                    row_["Unidad"] = row["unidadmedida"];
                    row_["Medida"] = row["valorunidadmedida"];
                    row_["Color"] = color.ImagenBit;
                    row_["Inventario"] = row["cantidad"];
                    miTabla.Rows.Add(row_);
                }
                dataTable.Clear();
                dataTable.Dispose();
                dataTable = null;
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        public long GetRowsConsultaInventarioNombre(string nombre)
        {
            try
            {
                CargarComandoStoredProcedure("count_listar_inventario_producto_nombre");
                miComando.Parameters.AddWithValue("nombre", nombre);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        public DataTable ConsultaInventarioCategoria(string categoria, int rowBase, int rowMax)
        {
            var dataTable = new DataTable();
            var miTabla = TablaInventario();
            try
            {
                CargarAdapterStoredProcedure("listar_inventario_producto_categoria");
                miAdapter.SelectCommand.Parameters.AddWithValue("categoria", categoria);
                miAdapter.Fill(rowBase, rowMax, dataTable);
                foreach (DataRow row in dataTable.Rows)
                {
                    var row_ = miTabla.NewRow();
                    var color = new ElColor();
                    color.MapaBits = (string)row["color"];
                    row_["Marca"] = row["categoria"];
                    row_["Codigo"] = row["codigo"];
                    row_["Nombre"] = row["nombre"];
                    row_["Unidad"] = row["unidadmedida"];
                    row_["Medida"] = row["valorunidadmedida"];
                    row_["Color"] = color.ImagenBit;
                    row_["Inventario"] = row["cantidad"];
                    miTabla.Rows.Add(row_);
                }
                dataTable.Clear();
                dataTable.Dispose();
                dataTable = null;
                return miTabla;
            }
            catch (Exception ex)
            {
                throw new Exception(ErrorProducto + ex.Message);
            }
        }

        public long GetRowsConsultaInventarioCategoria(string categoria)
        {
            try
            {
                CargarComandoStoredProcedure("count_listar_inventario_producto_categoria");
                miComando.Parameters.AddWithValue("categoria", categoria);
                miConexion.MiConexion.Open();
                var rows = Convert.ToInt64(miComando.ExecuteScalar());
                miConexion.MiConexion.Close();
                miComando.Dispose();
                return rows;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { miConexion.MiConexion.Close(); }
        }

        /// <summary>
        /// Obtiene una DataTable tipado para la vista de Resumen de Inventario.
        /// </summary>
        /// <returns></returns>
        private DataTable TablaInventario()
        {
            var tabla = new DataTable();
            tabla.Columns.Add(new DataColumn("Codigo", typeof(string)));
            tabla.Columns.Add(new DataColumn("Nombre", typeof(string)));
            tabla.Columns.Add(new DataColumn("Marca", typeof(string)));
            tabla.Columns.Add(new DataColumn("Fecha", typeof(DateTime)));
            tabla.Columns.Add(new DataColumn("Unidad", typeof(string)));
            tabla.Columns.Add(new DataColumn("Medida", typeof(string)));
            tabla.Columns.Add(new DataColumn("Color", typeof(System.Drawing.Image)));
            tabla.Columns.Add(new DataColumn("Inventario", typeof(string)));
            tabla.Columns.Add(new DataColumn("Fisico", typeof(string)));
            tabla.Columns.Add(new DataColumn("Diferencia", typeof(string)));
            tabla.Columns.Add(new DataColumn("Estado", typeof(bool)));
            return tabla;
        }

        /// <summary>
        /// Inicializa una nueva instancia de NpgsqlCommand de tipo Stored Procedure.
        /// </summary>
        /// <param name="cmd">Comando a ejecutar.</param>
        private void CargarComandoStoredProcedure(string cmd)
        {
            this.miComando = new NpgsqlCommand();
            this.miComando.Connection = this.miConexion.MiConexion;
            this.miComando.CommandType = CommandType.StoredProcedure;
            this.miComando.CommandText = cmd;
        }

        /// <summary>
        /// Inicializa una nueva instancia de NpgsqlDataAdapter de tipo StoredProcedure.
        /// </summary>
        /// <param name="cmd">Comando o Procedimiento a ejecutar.</param>
        private void CargarAdapterStoredProcedure(string cmd)
        {
            miAdapter = new NpgsqlDataAdapter(cmd, miConexion.MiConexion);
            miAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
        }
    }
}